public void AddEntry(string path, IsoEntry e) { var tmp = path.IndexOf('/'); if (tmp >= 0) { string subpath = path.Substring(tmp + 1).Trim(); path = path.Substring(0, tmp).Trim(); } }
private void susp_rr_rr(MemoryStream m, IsoEntry e) // IEEE P1282 Rock Ridge Protocol Identifier ( ? - I can't find this documented, but analysis of iso files reveals it's existence ) { int start = (int)m.Length; m.WriteByte((byte)'R'); m.WriteByte((byte)'R'); m.WriteByte(5); // LEN_RR m.WriteByte(1); // Version m.WriteByte(e.RrFlags); // flags System.Diagnostics.Debug.Assert((m.Length - start) == 5); }
/// <summary> /// This function is responsible for generating directory records. However, since more than one directory /// record may be required to get all the information out, it defers the actual directory record generation /// to a sub-function DirectoryRecordEx(). /// </summary> /// <param Name="name">The real folder Name</param> /// <param Name="e">object containing info about the folder</param> /// <param Name="root">1==PVD's root entry, 2==root's "." entry, 0==everything else ( special stuff needs to happen for the root entries )</param> private void DirectoryRecord(string name, IsoEntry e, byte root) { byte[] fileName = this.generator.IsoName(name, true); string cont = DirectoryRecordEx(fileName, name, e, root, false); #if ROCKRIDGE while (cont.Length > 0) { cont = DirectoryRecordEx(fileName, cont, e, 0, true); } #endif }
private string susp_rr_nm(MemoryStream m, string name, byte available, IsoEntry e) // IEEE P1282 Alternate Name ( 4.1.4 ) { int start = (int)m.Length; if (m.Length > available) { throw new Exception("buffer overflow - internal design error"); } available -= (byte)m.Length; string cont = ""; byte flags = 0; if (name == ".") { flags |= 2; } else if (name == "..") { flags |= 4; } else if (name.Length > (available - 5)) { flags |= 1; // need another entry... cont = name.Substring(available - 5); name = name.Substring(0, available - 5); } e.RrFlags |= 0x08; m.WriteByte((byte)'N'); m.WriteByte((byte)'M'); m.WriteByte((byte)(name.Length + 5)); m.WriteByte(1); // version? m.WriteByte(flags); m.Write(this.generator.Ascii.GetBytes(name), 0, name.Length); System.Diagnostics.Debug.Assert((m.Length - start) == (name.Length + 5)); return(cont); }
/// <summary> /// add a file to the ISO ( common implementation - called by AddFile() and AddBootFile() ) /// </summary> private IsoFile AddFileEx(string path, FileInfo fileInfo) { string key; string[] ar = NormalizePath(path).Split('/'); int i; IsoFolder f = this.isoRoot; for (i = 0; i < ar.Length - 1; i++) { key = ar[i].Trim().ToLower(); if (!f.entries.ContainsKey(key)) { var subf = new IsoFolder(); subf.Name = ar[i].Trim(); f.entries[key] = subf; } IsoEntry e = f.entries[key]; if (e.IsFile) { throw new Exception("cannot create directory \"" + ar[i].Trim() + "\", a file by that Name already exists"); //return; } f = (IsoFolder)e; } var x = new IsoFile(fileInfo); x.Name = ar[i].Trim(); key = ar[i].Trim().ToLower(); if (f.entries.ContainsKey(key)) { //throw new Exception("file or folder by that Name already exists"); return((IsoFile)f.entries[key]); // just don't add it for now... } f.entries[key] = x; return(x); }
/// <summary> /// create directory in ISO file /// </summary> public void MkDir(string path) { IsoFolder f = this.isoRoot; string[] ar = NormalizePath(path).Split('/'); for (int i = 0; i < ar.Length; i++) { string key = ar[i].Trim().ToLower(); if (!f.entries.ContainsKey(key)) { var subf = new IsoFolder(); subf.Name = ar[i].Trim(); f.entries[key] = subf; } IsoEntry e = f.entries[key]; if (e.IsFile) { //throw new Exception("cannot create directory \"" + ar[i].Trim() + "\", a file by that Name already exists"); return; // already exists - silently fail for now } f = (IsoFolder)e; } }
private byte[] Susp(ref string name, IsoEntry e, bool root, bool secondPass, byte available) // IEEE P1282 SUSP { MemoryStream m = new MemoryStream(); bool dots = (name == "." || name == ".."); if (!secondPass) { if (root) { susp_base_sp(m); susp_base_ce(m); } if (e.RrFlags != 0) { susp_rr_rr(m, e); } } // TODO FIXME - write and generate susp_rr_tf() - timestamps... if (dots) { name = ""; } else if (name.Length > 0) { name = susp_rr_nm(m, name, available, e); } if ((m.Length & 1) != 0) { m.WriteByte(0); // padding } byte[] b = m.GetBuffer(); Array.Resize(ref b, (int)m.Length); return(b); }
private string susp_rr_nm(MemoryStream m, string name, byte available, IsoEntry e) // IEEE P1282 Alternate Name ( 4.1.4 ) { int start = (int)m.Length; if (m.Length > available) throw new Exception("buffer overflow - internal design error"); available -= (byte)m.Length; string cont = ""; byte flags = 0; if (name == ".") flags |= 2; else if (name == "..") flags |= 4; else if (name.Length > (available - 5)) { flags |= 1; // need another entry... cont = name.Substring(available - 5); name = name.Substring(0, available - 5); } e.RrFlags |= 0x08; m.WriteByte((byte)'N'); m.WriteByte((byte)'M'); m.WriteByte((byte)(name.Length + 5)); m.WriteByte(1); // version? m.WriteByte(flags); m.Write(this.generator.Ascii.GetBytes(name), 0, name.Length); System.Diagnostics.Debug.Assert((m.Length - start) == (name.Length + 5)); return cont; }
private byte[] Susp(ref string name, IsoEntry e, bool root, bool secondPass, byte available) // IEEE P1282 SUSP { MemoryStream m = new MemoryStream(); bool dots = (name == "." || name == ".."); if (!secondPass) { if (root) { susp_base_sp(m); susp_base_ce(m); } if (e.RrFlags != 0) susp_rr_rr(m, e); } // TODO FIXME - write and generate susp_rr_tf() - timestamps... if (dots) name = ""; else if (name.Length > 0) name = susp_rr_nm(m, name, available, e); if ((m.Length & 1) != 0) m.WriteByte(0); // padding byte[] b = m.GetBuffer(); Array.Resize(ref b, (int)m.Length); return b; }
private string DirectoryRecordEx(byte[] fileName, string realName, IsoEntry e, byte root, bool secondPass) { byte[] /*b_fi,*/ b_su = null; /*if (fileName == ".") { b_fi = new byte[] { 0 }; realName = ""; } else if (fileName == "..") { b_fi = new byte[] { 1 }; realName = ""; } else b_fi = generator.Ascii.GetBytes(fileName);*/ byte LEN_FI = (byte)fileName.Length; byte LEN_DR = (byte)(33 + LEN_FI); bool fi_padding = ((LEN_DR & 1) != 0); if (fi_padding) LEN_DR++; // as much as I HATE to do it, I have to generate this data in both passes for now. // I don't yet understand enough about what and how many DR entries have to be made to figure out how to do it "right" byte LEN_SU = 0; #if ROCKRIDGE if (root != 1) // don't generate susp on PVD's root entry... { b_su = Susp(ref realName, e, root == 2, secondPass, (byte)(255 - LEN_DR)); if (b_su.Length > 255) throw new NotImplementedException("can't yet handle SUSP > 255 bytes"); LEN_SU = (byte)b_su.Length; } else realName = ""; #endif LEN_DR += LEN_SU; var dr = new FieldValidator(this.generator); dr.Byte(LEN_DR, 1); // Length of Directory Record ( 9.1.1 ) dr.Byte(0, 2); // Extended Attribute Record Length ( 9.1.2 ) dr.IntLSBMSB(e.DataBlock, 3, 10); // Location of Extent ( 9.1.3 ) #if true // in this test - I round the data length up to the next multiple of 2048, didn't help fix my booting problem though... dr.IntLSBMSB(((e.DataLength - 1) / 2048 + 1) * 2048, 11, 18); // Data Length ( 9.1.4 ) #else dr.IntLSBMSB(e.DataLength, 11, 18); // Data Length ( 9.1.4 ) #endif dr.BinaryDateTime(System.DateTime.Now, 19, 25); // Recording Date and Time ( 9.1.5 ) byte flags = 0; if (e.IsFile) { IsoFile f = (IsoFile)e; if ((f.fileInfo.Attributes & FileAttributes.Hidden) != 0) flags |= 1; // hidden } else { // TODO FIXME - not supporting hidden folders right now //IsoFolder f = (IsoFolder)e; //if ((f.dirInfo.Attributes & DirectoryAttributes.Hidden) != 0) // flags |= 1; // hidden } if (e.IsFolder) flags |= 2; // directory #if false // I'm disabling this because analysing of a working ISO never sets this bit... if (real_name.Length == 0) flags |= 128; // final #endif dr.Byte(flags, 26); // flags ( 9.1.6 ) dr.Byte(0, 27); // File Unit Size ( 9.1.7 ) dr.Byte(0, 28); // Interleave Gap Size ( 9.1.8 ) dr.ShortLSBMSB(1, 29, 32); // Volume Sequence Number ( 9.1.9 ) dr.Byte(LEN_FI, 33); // Length of File Identifier ( 9.1.10 ) dr.Bytes(fileName, 34, 33 + LEN_FI); if (fi_padding) dr.Zero(34 + LEN_FI, 34 + LEN_FI); if (LEN_SU > 0) dr.Bytes(b_su, LEN_DR - LEN_SU + 1, LEN_DR); return realName; }
private string DirectoryRecordEx(byte[] fileName, string realName, IsoEntry e, byte root, bool secondPass) { byte[] /*b_fi,*/ b_su = null; /*if (fileName == ".") * { * b_fi = new byte[] { 0 }; * realName = ""; * } * else if (fileName == "..") * { * b_fi = new byte[] { 1 }; * realName = ""; * } * else * b_fi = generator.Ascii.GetBytes(fileName);*/ byte LEN_FI = (byte)fileName.Length; byte LEN_DR = (byte)(33 + LEN_FI); bool fi_padding = ((LEN_DR & 1) != 0); if (fi_padding) { LEN_DR++; } // as much as I HATE to do it, I have to generate this data in both passes for now. // I don't yet understand enough about what and how many DR entries have to be made to figure out how to do it "right" byte LEN_SU = 0; #if ROCKRIDGE if (root != 1) // don't generate susp on PVD's root entry... { b_su = Susp(ref realName, e, root == 2, secondPass, (byte)(255 - LEN_DR)); if (b_su.Length > 255) { throw new NotImplementedException("can't yet handle SUSP > 255 bytes"); } LEN_SU = (byte)b_su.Length; } else { realName = ""; } #endif LEN_DR += LEN_SU; var dr = new FieldValidator(this.generator); dr.Byte(LEN_DR, 1); // Length of Directory Record ( 9.1.1 ) dr.Byte(0, 2); // Extended Attribute Record Length ( 9.1.2 ) dr.IntLSBMSB(e.DataBlock, 3, 10); // Location of Extent ( 9.1.3 ) #if true // in this test - I round the data length up to the next multiple of 2048, didn't help fix my booting problem though... dr.IntLSBMSB(((e.DataLength - 1) / 2048 + 1) * 2048, 11, 18); // Data Length ( 9.1.4 ) #else dr.IntLSBMSB(e.DataLength, 11, 18); // Data Length ( 9.1.4 ) #endif dr.BinaryDateTime(System.DateTime.Now, 19, 25); // Recording Date and Time ( 9.1.5 ) byte flags = 0; if (e.IsFile) { IsoFile f = (IsoFile)e; if ((f.fileInfo.Attributes & FileAttributes.Hidden) != 0) { flags |= 1; // hidden } } else { // TODO FIXME - not supporting hidden folders right now //IsoFolder f = (IsoFolder)e; //if ((f.dirInfo.Attributes & DirectoryAttributes.Hidden) != 0) // flags |= 1; // hidden } if (e.IsFolder) { flags |= 2; // directory } #if false // I'm disabling this because analysing of a working ISO never sets this bit... if (real_name.Length == 0) { flags |= 128; // final } #endif dr.Byte(flags, 26); // flags ( 9.1.6 ) dr.Byte(0, 27); // File Unit Size ( 9.1.7 ) dr.Byte(0, 28); // Interleave Gap Size ( 9.1.8 ) dr.ShortLSBMSB(1, 29, 32); // Volume Sequence Number ( 9.1.9 ) dr.Byte(LEN_FI, 33); // Length of File Identifier ( 9.1.10 ) dr.Bytes(fileName, 34, 33 + LEN_FI); if (fi_padding) { dr.Zero(34 + LEN_FI, 34 + LEN_FI); } if (LEN_SU > 0) { dr.Bytes(b_su, LEN_DR - LEN_SU + 1, LEN_DR); } return(realName); }