public static unsafe PK_header ReadHeader(byte[] bytes) { PK_header header = new PK_header { data = new List <PK_field>() }; fixed(byte *buffer = bytes) { byte *cursor = buffer; header.tag = *(ushort *)cursor; cursor += 2; header.size = *(ushort *)cursor; cursor += 2; byte *startOfData = cursor; header.crc32 = *(uint *)cursor; cursor += 4; while (cursor - startOfData < header.size) { var field = new PK_field(); field.tag = *(ushort *)cursor; cursor += 2; field.size = *(ushort *)cursor; cursor += 2; field.value = new byte[field.size]; Marshal.Copy((IntPtr)cursor, field.value, 0, field.size); cursor += field.size; header.data.Add(field); } } return(header); }
public static unsafe byte[] WriteHeader(PK_header header) { var bufferSize = 8; //initial fixed size of PK_header var crc = new CRC32(); foreach (var field in header.data) { bufferSize += 4; //base field size bufferSize += field.size; } var buffer = new byte[bufferSize]; fixed(byte *bufferPtr = buffer) { var cursor = bufferPtr; *(ushort *)cursor = header.tag; cursor += 2; *(ushort *)cursor = header.size; cursor += 2; //skip past the crc, well fill it in later int *crcPtr = (int *)cursor; cursor += 4; foreach (var field in header.data) { *(ushort *)cursor = field.tag; cursor += 2; *(ushort *)cursor = field.size; cursor += 2; Marshal.Copy(field.value, 0, (IntPtr)cursor, field.value.Length); cursor += field.value.Length; } crc.SlurpBlock(buffer, 8, bufferSize - 8); *crcPtr = crc.Crc32Result; } return(buffer); }
public static byte[] MakeVMSExtraBlock(RecordTypes recordType, RecordLayouts layout, FileAttributes attributes, ushort recordSize, uint fileSize, byte bucketSize, ushort maxRecordSize, ushort defaultExtend, DateTime created, DateTime modified, uint ownerId, FileProtection system, FileProtection owner, FileProtection group, FileProtection world) { var headerResult = new PK_header { tag = VMSAttributeHeader, size = VMSAttributeSize, data = new List <PK_field>() }; var evenFileSize = Math.DivRem(fileSize, 512, out var fileSizeRemainder) + 1; FatDef fatDef = new FatDef { b_rtype = MakeRecordType(recordType, layout), b_rattrib = (byte)attributes, w_rsize = recordSize, l_hiblk = (uint)(((evenFileSize + 1) << 16) | ((evenFileSize + 1) >> 16)), l_efblk = (uint)((evenFileSize << 16) | (evenFileSize >> 16)), w_ffbyte = (ushort)fileSizeRemainder, b_bktsize = bucketSize, b_vfcsize = (byte)(recordType == RecordTypes.C_VFC ? 2 : 0), w_maxrec = maxRecordSize, w_defext = defaultExtend, w_gbc = 0 }; headerResult.data.Add(new PK_field { size = 32, tag = 4, value = WriteFATDef(fatDef) }); headerResult.data.Add(new PK_field { size = 4, tag = 3, value = BitConverter.GetBytes((int)0) }); headerResult.data.Add(new PK_field { size = 8, tag = 17, value = ConvertToSmithsonianTime(created) }); headerResult.data.Add(new PK_field { size = 8, tag = 18, value = ConvertToSmithsonianTime(modified) }); headerResult.data.Add(new PK_field { size = 8, tag = 19, value = BitConverter.GetBytes((long)0) }); headerResult.data.Add(new PK_field { size = 8, tag = 20, value = BitConverter.GetBytes((long)0) }); headerResult.data.Add(new PK_field { size = 2, tag = 13, value = new byte[] { 1, 0 } }); headerResult.data.Add(new PK_field { size = 4, tag = 21, value = BitConverter.GetBytes(ownerId) }); headerResult.data.Add( new PK_field { size = 2, tag = 22, value = MakeProtection(system, owner, group, world) }); headerResult.data.Add(new PK_field { size = 2, tag = 23, value = new byte[] { 0, 0 } }); headerResult.data.Add(new PK_field { size = 1, tag = 29, value = new byte[] { 0 } }); return(WriteHeader(headerResult)); }